diff -ur source/config/mh-serenity source.serenity/config/mh-serenity
--- source/config/mh-serenity	1970-01-01 01:00:00.000000000 +0100
+++ source.serenity/config/mh-serenity	2021-04-11 09:20:23.857575570 +0200
@@ -0,0 +1,87 @@
+## -*-makefile-*-
+## Copyright (C) 2016 and later: Unicode, Inc. and others.
+## License & terms of use: http://www.unicode.org/copyright.html
+## Linux-specific setup
+## Copyright (c) 1999-2013, International Business Machines Corporation and
+## others. All Rights Reserved.
+
+## Commands to generate dependency files
+GEN_DEPS.c=  $(CC) -E -MM $(DEFS) $(CPPFLAGS)
+GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS) $(CXXFLAGS)
+
+## Flags for position independent code
+SHAREDLIBCFLAGS = -fPIC
+SHAREDLIBCXXFLAGS = -fPIC
+SHAREDLIBCPPFLAGS = -DPIC
+
+## Additional flags when building libraries and with threads
+THREADSCPPFLAGS = -D_REENTRANT
+LIBCPPFLAGS =
+
+## Compiler switch to embed a runtime search path
+LD_RPATH= -Wl,-zorigin,-rpath,'$$'ORIGIN 
+LD_RPATH_PRE = -Wl,-rpath,
+
+## These are the library specific LDFLAGS
+LDFLAGSICUDT=-nodefaultlibs -nostdlib
+
+## Compiler switch to embed a library name
+# The initial tab in the next line is to prevent icu-config from reading it.
+	LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET))
+#SH# # We can't depend on MIDDLE_SO_TARGET being set.
+#SH# LD_SONAME=
+
+## Shared library options
+LD_SOOPTIONS= -Wl,-Bsymbolic
+
+## Shared object suffix
+SO = so
+## Non-shared intermediate object suffix
+STATIC_O = ao
+
+## Compilation rules
+%.$(STATIC_O): $(srcdir)/%.c
+	$(call SILENT_COMPILE,$(strip $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS)) -o $@ $<)
+%.o: $(srcdir)/%.c
+	$(call SILENT_COMPILE,$(strip $(COMPILE.c) $(DYNAMICCPPFLAGS) $(DYNAMICCFLAGS)) -o $@ $<)
+
+%.$(STATIC_O): $(srcdir)/%.cpp
+	$(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS)) -o $@ $<)
+%.o: $(srcdir)/%.cpp
+	$(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS)) -o $@ $<)
+
+
+## Dependency rules
+%.d: $(srcdir)/%.c
+	$(call ICU_MSG,(deps)) $<
+	@$(SHELL) -ec '$(GEN_DEPS.c) $< \
+		| sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+		[ -s $@ ] || rm -f $@'
+
+%.d: $(srcdir)/%.cpp
+	$(call ICU_MSG,(deps)) $<
+	@$(SHELL) -ec '$(GEN_DEPS.cc) $< \
+		| sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+		[ -s $@ ] || rm -f $@'
+
+## Versioned libraries rules
+
+%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
+	$(RM) $@ && ln -s ${<F} $@
+%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
+	$(RM) $@ && ln -s ${*F}.$(SO).$(SO_TARGET_VERSION) $@
+
+##  Bind internal references
+
+# LDflags that pkgdata will use
+BIR_LDFLAGS= -Wl,-Bsymbolic
+
+# Dependencies [i.e. map files] for the final library
+BIR_DEPS=
+
+## Remove shared library 's'
+STATIC_PREFIX_WHEN_USED = 
+STATIC_PREFIX = 
+
+## End Linux-specific setup
+
diff -ur source/common/umutex.cpp source.serenity/common/umutex.cpp
--- source/common/umutex.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/common/umutex.cpp	2021-04-11 09:45:50.785341646 +0200
@@ -44,40 +44,56 @@
  *************************************************************************************************/
 
 namespace {
+#ifndef __serenity__
 std::mutex *initMutex;
 std::condition_variable *initCondition;
+#endif
 
 // The ICU global mutex.
 // Used when ICU implementation code passes nullptr for the mutex pointer.
 UMutex globalMutex;
 
+#ifndef __serenity__
 std::once_flag initFlag;
 std::once_flag *pInitFlag = &initFlag;
+#endif
 
 }  // Anonymous namespace
 
 U_CDECL_BEGIN
 static UBool U_CALLCONV umtx_cleanup() {
+#ifndef __serenity__
     initMutex->~mutex();
     initCondition->~condition_variable();
+#endif
     UMutex::cleanup();
 
     // Reset the once_flag, by destructing it and creating a fresh one in its place.
     // Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once().
+#ifndef __serenity__
     pInitFlag->~once_flag();
     pInitFlag = new(&initFlag) std::once_flag();
+#endif
     return true;
 }
 
 static void U_CALLCONV umtx_init() {
+#ifndef __serenity__
     initMutex = STATIC_NEW(std::mutex);
     initCondition = STATIC_NEW(std::condition_variable);
+#endif
     ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup);
 }
 U_CDECL_END
 
 
-std::mutex *UMutex::getMutex() {
+#ifndef __serenity__
+std::mutex
+#else
+void
+#endif
+*UMutex::getMutex() {
+#ifndef __serenity__
     std::mutex *retPtr = fMutex.load(std::memory_order_acquire);
     if (retPtr == nullptr) {
         std::call_once(*pInitFlag, umtx_init);
@@ -92,6 +108,9 @@
     }
     U_ASSERT(retPtr != nullptr);
     return retPtr;
+#else
+    return this;
+#endif
 }
 
 UMutex *UMutex::gListHead = nullptr;
@@ -99,8 +118,10 @@
 void UMutex::cleanup() {
     UMutex *next = nullptr;
     for (UMutex *m = gListHead; m != nullptr; m = next) {
+#ifndef __serenity__
         (*m->fMutex).~mutex();
         m->fMutex = nullptr;
+#endif
         next = m->fListLink;
         m->fListLink = nullptr;
     }
@@ -143,8 +164,12 @@
 //
 U_COMMON_API UBool U_EXPORT2
 umtx_initImplPreInit(UInitOnce &uio) {
+#ifndef __serenity__
     std::call_once(*pInitFlag, umtx_init);
     std::unique_lock<std::mutex> lock(*initMutex);
+#else
+    umtx_init();
+#endif
     if (umtx_loadAcquire(uio.fState) == 0) {
         umtx_storeRelease(uio.fState, 1);
         return true;      // Caller will next call the init function.
@@ -152,7 +177,9 @@
         while (umtx_loadAcquire(uio.fState) == 1) {
             // Another thread is currently running the initialization.
             // Wait until it completes.
+#ifndef __serenity__
             initCondition->wait(lock);
+#endif
         }
         U_ASSERT(uio.fState == 2);
         return false;
@@ -169,10 +196,14 @@
 U_COMMON_API void U_EXPORT2
 umtx_initImplPostInit(UInitOnce &uio) {
     {
+#ifndef __serenity__
         std::unique_lock<std::mutex> lock(*initMutex);
+#endif
         umtx_storeRelease(uio.fState, 2);
     }
+#ifndef __serenity__
     initCondition->notify_all();
+#endif
 }
 
 U_NAMESPACE_END
diff -ur source/common/umutex.h source.serenity/common/umutex.h
--- source/common/umutex.h	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/common/umutex.h	2021-04-11 09:33:17.301246150 +0200
@@ -231,17 +231,25 @@
 
     // requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard
     void lock() {
+#ifndef __serenity__
         std::mutex *m = fMutex.load(std::memory_order_acquire);
         if (m == nullptr) { m = getMutex(); }
         m->lock();
+#endif
+    }
+    void unlock() {
+#ifndef __serenity__
+        fMutex.load(std::memory_order_relaxed)->unlock();
+#endif
     }
-    void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); }
 
     static void cleanup();
 
 private:
+#ifndef __serenity__
     alignas(std::mutex) char fStorage[sizeof(std::mutex)] {};
     std::atomic<std::mutex *> fMutex { nullptr };
+#endif
 
     /** All initialized UMutexes are kept in a linked list, so that they can be found,
      * and the underlying std::mutex destructed, by u_cleanup().
@@ -253,7 +261,12 @@
      * Initial fast check is inline, in lock().  The returned value may never
      * be nullptr.
      */
-    std::mutex *getMutex();
+#ifndef __serenity__
+    std::mutex
+#else
+    void
+#endif
+    *getMutex();
 };
 
 
diff -ur source/common/unifiedcache.cpp source.serenity/common/unifiedcache.cpp
--- source/common/unifiedcache.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/common/unifiedcache.cpp	2021-04-11 09:44:51.810895675 +0200
@@ -13,16 +13,20 @@
 #include "unifiedcache.h"
 
 #include <algorithm>      // For std::max()
+#ifndef __serenity__
 #include <mutex>
+#endif
 
 #include "uassert.h"
 #include "uhash.h"
 #include "ucln_cmn.h"
 
 static icu::UnifiedCache *gCache = NULL;
+#ifndef __serenity__
 static std::mutex *gCacheMutex = nullptr;
 static std::condition_variable *gInProgressValueAddedCond;
 static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
+#endif
 
 static const int32_t MAX_EVICT_ITERATIONS = 10;
 static const int32_t DEFAULT_MAX_UNUSED = 1000;
@@ -31,13 +35,17 @@
 
 U_CDECL_BEGIN
 static UBool U_CALLCONV unifiedcache_cleanup() {
+#ifndef __serenity__
     gCacheInitOnce.reset();
+#endif
     delete gCache;
     gCache = nullptr;
+#ifndef __serenity__
     gCacheMutex->~mutex();
     gCacheMutex = nullptr;
     gInProgressValueAddedCond->~condition_variable();
     gInProgressValueAddedCond = nullptr;
+#endif
     return TRUE;
 }
 U_CDECL_END
@@ -72,8 +80,10 @@
     ucln_common_registerCleanup(
             UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup);
 
+#ifndef __serenity__
     gCacheMutex = STATIC_NEW(std::mutex);
     gInProgressValueAddedCond = STATIC_NEW(std::condition_variable);
+#endif
     gCache = new UnifiedCache(status);
     if (gCache == NULL) {
         status = U_MEMORY_ALLOCATION_ERROR;
@@ -86,7 +96,11 @@
 }
 
 UnifiedCache *UnifiedCache::getInstance(UErrorCode &status) {
+#ifndef __serenity__
     umtx_initOnce(gCacheInitOnce, &cacheInit, status);
+#else
+    cacheInit(status);
+#endif
     if (U_FAILURE(status)) {
         return NULL;
     }
@@ -135,28 +149,38 @@
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     fMaxUnused = count;
     fMaxPercentageOfInUse = percentageOfInUseItems;
 }
 
 int32_t UnifiedCache::unusedCount() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     return uhash_count(fHashtable) - fNumValuesInUse;
 }
 
 int64_t UnifiedCache::autoEvictedCount() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     return fAutoEvictedCount;
 }
 
 int32_t UnifiedCache::keyCount() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     return uhash_count(fHashtable);
 }
 
 void UnifiedCache::flush() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
 
     // Use a loop in case cache items that are flushed held hard references to
     // other cache items making those additional cache items eligible for
@@ -165,7 +189,9 @@
 }
 
 void UnifiedCache::handleUnreferencedObject() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     --fNumValuesInUse;
     _runEvictionSlice();
 }
@@ -184,7 +210,9 @@
 }
 
 void UnifiedCache::dumpContents() const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     _dumpContents();
 }
 
@@ -224,7 +252,9 @@
         // Now all that should be left in the cache are entries that refer to
         // each other and entries with hard references from outside the cache.
         // Nothing we can do about these so proceed to wipe out the cache.
+#ifndef __serenity__
         std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
         _flush(TRUE);
     }
     uhash_close(fHashtable);
@@ -325,7 +355,9 @@
         const CacheKeyBase &key,
         const SharedObject *&value,
         UErrorCode &status) const {
+#ifndef __serenity__
     std::lock_guard<std::mutex> lock(*gCacheMutex);
+#endif
     const UHashElement *element = uhash_find(fHashtable, &key);
     if (element != NULL && !_inProgress(element)) {
         _fetch(element, value, status);
@@ -350,14 +382,18 @@
         UErrorCode &status) const {
     U_ASSERT(value == NULL);
     U_ASSERT(status == U_ZERO_ERROR);
+#ifndef __serenity__
     std::unique_lock<std::mutex> lock(*gCacheMutex);
+#endif
     const UHashElement *element = uhash_find(fHashtable, &key);
 
     // If the hash table contains an inProgress placeholder entry for this key,
     // this means that another thread is currently constructing the value object.
     // Loop, waiting for that construction to complete.
      while (element != NULL && _inProgress(element)) {
+#ifndef __serenity__
          gInProgressValueAddedCond->wait(lock);
+#endif
          element = uhash_find(fHashtable, &key);
     }
 
@@ -430,7 +466,9 @@
 
     // Tell waiting threads that we replace in-progress status with
     // an error.
+#ifndef __serenity__
     gInProgressValueAddedCond->notify_all();
+#endif
 }
 
 void UnifiedCache::_fetch(
diff -ur source/config.sub source.serenity/config.sub
--- source/config.sub	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/config.sub	2021-04-11 07:59:52.531086431 +0200
@@ -1416,7 +1416,7 @@
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
-	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*)
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -serenity*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
diff -ur source/configure source.serenity/configure
--- source/configure	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/configure	2021-04-11 09:24:04.971314734 +0200
@@ -5274,6 +5274,8 @@
 	else
 		icu_cv_host_frag=mh-cygwin-msvc
 	fi ;;
+*-serenity*)
+	icu_cv_host_frag=mh-serenity ;;
 *-*-mingw*)
 	if test "$GCC" = yes; then
                 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff -ur source/i18n/decimfmt.cpp source.serenity/i18n/decimfmt.cpp
--- source/i18n/decimfmt.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/i18n/decimfmt.cpp	2021-04-11 09:58:25.946465400 +0200
@@ -1827,13 +1827,21 @@
     if (!fields->canUseFastFormat) {
         return false;
     }
+#ifndef __serenity__
     if (std::isnan(input)
+#else
+    if (isnan(input)
+#endif
             || uprv_trunc(input) != input
             || input <= INT32_MIN
             || input > INT32_MAX) {
         return false;
     }
+#ifndef __serenity__
     doFastFormatInt32(static_cast<int32_t>(input), std::signbit(input), output);
+#else
+    doFastFormatInt32(static_cast<int32_t>(input), signbit(input), output);
+#endif
     return true;
 }
 
diff -ur source/i18n/number_decimalquantity.cpp source.serenity/i18n/number_decimalquantity.cpp
--- source/i18n/number_decimalquantity.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/i18n/number_decimalquantity.cpp	2021-04-11 10:00:59.729454484 +0200
@@ -419,13 +419,25 @@
     setBcdToZero();
     flags = 0;
     // signbit() from <math.h> handles +0.0 vs -0.0
+#ifndef __serenity__
     if (std::signbit(n)) {
+#else
+    if (signbit(n)) {
+#endif
         flags |= NEGATIVE_FLAG;
         n = -n;
     }
+#ifndef __serenity__
     if (std::isnan(n) != 0) {
+#else
+    if (isnan(n) != 0) {
+#endif
         flags |= NAN_FLAG;
+#ifndef __serenity__
     } else if (std::isfinite(n) == 0) {
+#else
+    } else if (isfinite(n) == 0) {
+#endif
         flags |= INFINITY_FLAG;
     } else if (n != 0) {
         _setToDoubleFast(n);
diff -ur source/i18n/number_utils.cpp source.serenity/i18n/number_utils.cpp
--- source/i18n/number_utils.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/i18n/number_utils.cpp	2021-04-11 09:59:55.181535153 +0200
@@ -130,7 +130,11 @@
 
 void DecNum::setTo(double d, UErrorCode& status) {
     // Need to check for NaN and Infinity before going into DoubleToStringConverter
+#ifndef __serenity__
     if (std::isnan(d) != 0 || std::isfinite(d) == 0) {
+#else
+    if (isnan(d) != 0 || isfinite(d) == 0) {
+#endif
         status = U_UNSUPPORTED_ERROR;
         return;
     }
@@ -157,7 +161,11 @@
 
     // Set exponent and bitmask. Note that DoubleToStringConverter does not do negatives.
     fData.getAlias()->exponent += point - length;
+#ifndef __serenity__
     fData.getAlias()->bits |= static_cast<uint8_t>(std::signbit(d) ? DECNEG : 0);
+#else
+    fData.getAlias()->bits |= static_cast<uint8_t>(signbit(d) ? DECNEG : 0);
+#endif
 }
 
 void DecNum::_setTo(const char* str, int32_t maxDigits, UErrorCode& status) {
diff -ur source/i18n/reldatefmt.cpp source.serenity/i18n/reldatefmt.cpp
--- source/i18n/reldatefmt.cpp	2021-04-08 02:10:27.000000000 +0200
+++ source.serenity/i18n/reldatefmt.cpp	2021-04-11 09:55:40.409893218 +0200
@@ -1008,7 +1008,11 @@
         return;
     }
     UDateDirection direction = UDAT_DIRECTION_NEXT;
+#ifndef __serenity__
     if (std::signbit(offset)) { // needed to handle -0.0
+#else
+    if (signbit(offset)) {
+#endif
         direction = UDAT_DIRECTION_LAST;
         offset = -offset;
     }
